// 执行器文件

// export let evaluator = {}

import { ExecutionContext, Reference, Realm } from './runtime.js'

export class Evaluator { // 使用对象存储对应的执行方法(运行时)
  constructor() {
    // 是在JS引擎的一个新实例被建立起来的时候产生的
    this.realm = new Realm()
    this.globalObject = {}
    // 每次函数调用时有一个栈来管理ExecutionContext
    this.ecs = [new ExecutionContext(this.realm, this.globalObject)]
  }
  evaluate(node) { // 逐级的执行语法树 语义分析
    // console.log(node)
    if (this[node.type]) {
      let r = this[node.type](node)
      console.log(r)
      return r
    }
  }
  Program(node) {
    // console.log(node)
    return this.evaluate(node.children[0])
  }
  StatementList(node) {
    // console.log(node)
    if (node.children.length === 1) {
      return this.evaluate(node.children[0])
    } else { // js标准里面的定义
      this.evaluate(node.children[0])
      return this.evaluate(node.children[1])
    }
  }
  Statement(node) {
    return this.evaluate(node.children[0])
  }
  VariableDeclaration(node) { // 运行时，变量需要执行
    // console.log("Declare variable", node.children[1].name)
    // 取到当前的ExecutionContext
    let runningEc = this.ecs[this.ecs.length - 1] // 栈顶
    runningEc.variableEnvironment[node.children[1].name]
  }
  ExpressionStatement(node) {
    return this.evaluate(node.children[0])
  }
  Expression(node) {
    return this.evaluate(node.children[0])
  }
  AdditiveExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0])
    else {
      // TOOO
    }
  }
  MultiplicativeExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0])
    else {
      // TOOO
    }
  }
  PrimaryExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0])
  }
  Literal(node) {
    return this.evaluate(node.children[0])
  }
  NumbericLiteral(node) { // 处理 number 类型

    let str = node.value
    let l = str.length
    let value = 0
    let n = 10 // 十进制

    if (str.match(/^0b/)) { // 判断是否为二进制
      n = 2
      l -= 2
    } else if (str.match(/^0o/)) { // 八进制
      n = 8
      l -= 2
    } else if (str.match(/^0x/)) { // 十六进制
      n = 16
      l -= 2
    }

    while(l--) { // '0'.charCodeAt(0) 得到0位的码点
      let c = str.charCodeAt(str.length - l - 1)
      if(c >= 'a'.charCodeAt(0)) {
        c = c - 'a'.charCodeAt(0) + 10
      } else if (c >= 'A'.charCodeAt(0)) {
        c = c - 'A'.charCodeAt(0) + 10
      } else if (c >= '0'.charCodeAt(0)) {
        c = c - '0'.charCodeAt(0)
      }

      value = value * n + c
      // value = value * n * str.charCodeAt(str.length - l - 1) - '0'.charCodeAt(0)
    }

    return Number(node.value)
    // return evaluate(node.children[0])
  }
  StringLiteral(node) { // 不去做 utf-16的处理
    // console.log(node.value)
    let i = 1
    let result = []

    for (let i = 1; i < node.value.length - 1; i++) {
      if (node.value[i] === '\\') { // 转义
        ++ i
        let c = node.value[i]
        let map = { // 默认BMP 用一个UTF-16的表示的000000~ffffff
          "\"": "\"",
          "\'": "\'",
          "\\": "\\",
          "0": String.fromCharCode(0x0000),
          "b": String.fromCharCode(0x0008),
          "f": String.fromCharCode(0x000C),
          "n": String.fromCharCode(0x000A),
          "r": String.fromCharCode(0x000D),
          "t": String.fromCharCode(0x0009),
          "v": String.fromCharCode(0x000B)
        }
        if (c in map) { // 如果存在
          result.push(map[c])
        } else {
          result.push(c)
        }
      } else {
        result.push(node.value[i])
      }
    }
    console.log(result)
    return result.join('')
  }
  ObjectLiteral(node) {
    if(node.children.length === 2)
      return {};
    if(node.children.length === 3) { // kv对 Object包含property和原型两部分
      let object = new Map() // 用map类型来保存property部分
      this.PropertyList(node.children[1], object) // [0]、[2]都是花括号
      
      // object.prototype = 
      return object
    }
  }
  PropertyList(node, object) {
    if(node.children.length === 1) {
      this.Property(node.children[0], object)
    } else { // 如果有多个可以递归
      this.PropertyList(node.children[0], object) // [1]是逗号
      this.Property(node.children[2], object)
    }
  }
  Property(node, object) {
    let name; // 处理两种类型
    if (node.children[0].type === 'Identifier') {
      name  = node.children[0].name
    } else if (node.children[0].type === 'StringLiteral') {
      name = this.evaluate(node.children[0])
    }
    // object.set(evaluate(node.children[0]), evaluate(node.children[2]))
    object.set(name, { // 一个kv对不能直接单单写值，还要有属性
      value: this.evaluate(node.children[2]),
      writable: true,
      enumerable: true,
      configurable: true
    })
  }
  AssignmentExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0]);
    let left = this.evaluate(node.children[0]);
    let right = this.evaluate(node.children[2]);
    left.set(right) // 认为左边的值是一个Reference类型
  }
  LogicalORExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0]);
    let result = this.evaluate(node.children[0])
    if (result) { // 短路逻辑，因为是或 当一个条件为true时、为false时
      return result;
    } else {
      return this.evaluate(node.children[2])
    }
  }
  LogicalANDExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0]);
    let result = this.evaluate(node.children[0])
    if (!result) { // 短路逻辑，因为是&&  当一个条件为true时、为false时
      return result;
    } else {
      return this.evaluate(node.children[2])
    }
  }
  LeftHandSideExpression(node) {
    return this.evaluate(node.children[0]);
  }
  CallExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0]);
    if (node.children.length === 2) { // 如果有 new 关键字
      let func = this.evaluate(node.children[0]);
      let args = this.evaluate(node.children[1]);
      return func.call(args);
    }
  }
  NewExpression(node) {
    if(node.children.length === 1)
      return this.evaluate(node.children[0]);
    if (node.children.length === 2) { // 如果有 new 关键字
      let cls = this.evaluate(node.children[1]);
      return cls.construct();
      /* new 关键字到底发生了什么 
      let object = this.realm.Object.construct(); // 这个object 是要实现的一个js里面的object
      let cls = this.evaluate(node.children[1]);
      let result = cls.call(object)
      if (typeof result === 'object') { // 如果返回的是一个对象就返回本身的值
        return result
      } else {
        return object
      }
      */
    }
  }
  MemberExpression(node) { // 与对象相关
    if(node.children.length === 1)
      return this.evaluate(node.children[0]);
    if (node.children.length === 3) {
      let obj = this.evaluate(node.children[0]).get();
      let prop = obj.get(node.children[2].name);
      if ('value' in prop) return prop.value
      if ('get' in prop) return prop.get.call(obj)
    }
  }
  Identifier(node) {
    // 取到当前的ExecutionContext
    let runningEc = this.ecs[this.ecs.length - 1] // 栈顶
    // return runningEc.lexicalEnvironment[node.name] // 取变量(直接取是比较草率的，不应只读)
    // 用一个Reference 类型把属性值与名存起来
    return new Reference(runningEc.lexicalEnvironment, node.name)
  }
  // EOF() {
  //   return null
  // }

}


